#include "SampleFrame.h"

#include "core/ImgCutter.h"

#include <QPainter>
#include <QMouseEvent>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QScrollBar>
#include <QInputDialog>
#include <QApplication>

#include <QDebug>

SampleFrame::SampleFrame(QWidget *parent) :
    QGraphicsView(parent)
{
    setScene(new QGraphicsScene(this));

    current_rect_item = NULL;
    pixmap_item = NULL;

    mouse_action = NoFocus;

    setAlignment(Qt::AlignLeft | Qt::AlignTop);
    scene()->activeWindow();
}

void SampleFrame::setPixmap(const QString &pixmap_path){
    if(pixmap_item != NULL){
        scene()->removeItem(pixmap_item);
    }

    pixmap_item = scene()->addPixmap(QPixmap(pixmap_path));
}

const QMap<QString, QRect> *SampleFrame::getRectMap() const{
    static QMap<QString, QRect> map;

    map.clear();

    int cur_id = 0;
    foreach(const QGraphicsRectItem *item, rect_item_list){
        cur_id++;

        if(item->childItems().isEmpty()){
            map[QString::number(cur_id)] = item->rect().toRect();
        }else{
            QGraphicsTextItem *name_item = (QGraphicsTextItem *) item->childItems().first();
            map[name_item->toPlainText()] = item->rect().toRect();
        }
    }

    return &map;
}

void SampleFrame::saveRectMap(const QString &file_path){
    QByteArray content;
    QMapIterator<QString, QRect> iter(*getRectMap());
    while(iter.hasNext()){
        iter.next();
        content
            .append(iter.key()).append(' ')
            .append(QString::number(iter.value().left())).append(' ')
            .append(QString::number(iter.value().top())).append(' ')
            .append(QString::number(iter.value().width())).append(' ')
            .append(QString::number(iter.value().height())).append('|');
    }

    content.remove(content.length() - 1, 1);

    QFile file(file_path);
    file.open(QFile::WriteOnly);
    file.write(content);
    file.close();
}

void SampleFrame::loadRectMap(const QString &file_path){
    clearRects();

    QFile file(file_path);
    if(file.open(QFile::ReadOnly)){
        foreach(const QByteArray &tmp, file.readAll().split('|')){
            if(tmp.isEmpty()){
                continue;
            }

            QList<QByteArray> line = tmp.split(' ');

            current_rect.setRect(line[1].toInt(), line[2].toInt(), line[3].toInt(), line[4].toInt());
            addCurrentRectItem();
            rect_item_list.append(current_rect_item);

            QGraphicsTextItem *text_item = scene()->addText(line[0]);
            text_item->setParentItem(current_rect_item);
            text_item->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
            text_item->setPos(current_rect.topLeft());

            file.close();
        }
    }else{
        emit error(tr("JPG Tailor failed to open the file."));
    }
}

void SampleFrame::mousePressEvent(QMouseEvent *event){
    QPoint event_pos = realPos(event);

    foreach(QGraphicsRectItem *other, rect_item_list){
        if(other != NULL){
            other->setPen(QPen(Qt::black, 1, Qt::DashLine));
        }
    }

    QGraphicsRectItem *item = getRectContainsPoint(event_pos);
    if(item != NULL){
        mouse_action = MovingRect;

        item->setPen(QPen(Qt::blue, 1, Qt::SolidLine));

        current_rect_item = item;
        current_rect = item->rect().toRect();

        offset_point = event_pos;

    }else{
        mouse_action = DrawingRect;
        current_rect.setTopLeft(event_pos);
        addCurrentRectItem();

        offset_point = current_rect.topLeft();
    }
}

void SampleFrame::mouseMoveEvent(QMouseEvent *event){
    QPoint event_pos = realPos(event);

    if(mouse_action == DrawingRect){
        int right = event_pos.x();
        if(right < offset_point.x()){
            current_rect.setLeft(right);
            current_rect.setRight(offset_point.x());
        }else{
            current_rect.setLeft(offset_point.x());
            current_rect.setRight(right);
        }

        int bottom = event_pos.y();
        if(bottom < offset_point.y()){
            current_rect.setTop(bottom);
            current_rect.setBottom(offset_point.y());
        }else{
            current_rect.setTop(offset_point.y());
            current_rect.setBottom(bottom);
        }

        current_rect_item->setRect(current_rect);

    }else if(mouse_action == MovingRect){
        int x = event_pos.x() - offset_point.x();
        current_rect.setLeft(current_rect.left() + x);
        current_rect.setRight(current_rect.right() + x);

        int y = event_pos.y() - offset_point.y();
        current_rect.setTop(current_rect.top() + y);
        current_rect.setBottom(current_rect.bottom() + y);

        current_rect_item->setRect(current_rect);
        if(!current_rect_item->childItems().isEmpty()){
            current_rect_item->childItems().first()->setPos(current_rect.topLeft());
        }

        offset_point = event_pos;
    }
}

void SampleFrame::mouseReleaseEvent(QMouseEvent *event){
    if(mouse_action == DrawingRect){
        if(current_rect.width() > 1 && current_rect.height() > 1){
            rect_item_list.append(current_rect_item);
        }else{
            scene()->removeItem(current_rect_item);
            emit blankAreaClicked();
        }
    }

    mouse_action = NoFocus;
    current_rect.setRect(0, 0, 0, 0);
}

void SampleFrame::mouseDoubleClickEvent(QMouseEvent *event){
    QPoint pos = realPos(event);

    QGraphicsRectItem *item = getRectContainsPoint(pos);
    if(item != NULL){
        if(item->childItems().isEmpty()){
            QString text = QInputDialog::getText(this, tr("Assign a name for the rect"), tr("Please Input a name for the current rect:"));
            QGraphicsTextItem *text_item = scene()->addText(text);
            text_item->setParentItem(item);
            text_item->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
            text_item->setPos(item->rect().topLeft());

        }else{
            QGraphicsTextItem *text_item = (QGraphicsTextItem *) item->childItems().first();
            QString text = QInputDialog::getText(this, tr("Assign a name for the rect"), tr("Please Input a name for the current rect:"), QLineEdit::Normal, text_item->toPlainText());
            text_item->setPlainText(text);
        }
        return;
    }else{
        emit blankAreaDblClicked();
    }
}

const QPoint &SampleFrame::realPos(QMouseEvent *event){
    static QPoint pos;
    pos.setX(event->pos().x() + horizontalScrollBar()->value());
    pos.setY(event->pos().y() + verticalScrollBar()->value());
    return pos;
}

void SampleFrame::keyReleaseEvent(QKeyEvent *event){
    if(event->key() == Qt::Key_Delete && current_rect_item != NULL){
        rect_item_list.removeOne(current_rect_item);
        scene()->removeItem(current_rect_item);
        current_rect.setRect(0, 0, 0, 0);
    }
}

void SampleFrame::clear(){
    clearRects();
    scene()->clear();
}

void SampleFrame::clearRects(){
    foreach(QGraphicsRectItem *item, rect_item_list){
        scene()->removeItem(item);
    }

    rect_item_list.clear();
}

void SampleFrame::addCurrentRectItem(){
    current_rect_item = scene()->addRect(current_rect, QPen(Qt::black, 1, Qt::DashLine), QBrush(QColor(0, 0, 255, 20)));
    current_rect_item->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}

QGraphicsRectItem *SampleFrame::getRectContainsPoint(const QPoint &event_pos){
    foreach(QGraphicsRectItem *item, rect_item_list){
        if(item->contains(event_pos)){
            return item;
        }
    }

    return NULL;
}
